package cn.songtx.iot.controller;

import cn.songtx.iot.pojo.*;
import cn.songtx.iot.service.ISysEquipmentService;
import cn.songtx.iot.service.ISysFamilyService;
import cn.songtx.iot.service.ISysRoomService;
import cn.songtx.iot.vo.FamilyRoomEquipmentVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping("/equipment")                             // 分级请求路径
@RequiredArgsConstructor                                  // 注入必备的构造函数
public class SysEquipmentController {

    /*
     * 1.创建设备,不带id是创建,带id是修改
     * 2.接收一个id,根据id逻辑删除
     * 3.接收一个list,批量逻辑删除
     * 4.修改设备属性
     * 5.分页查询
     * 6.带组装条件的条件分页查询
     * */
    private final ISysFamilyService familyService;
    private final ISysRoomService roomService;
    private final ISysEquipmentService equipmentService;

    /**
     * RequsetMapping注解派生出@GetMapping、@PostMapping、@PutMapping和@DeleteMapping4个注解
     * method=RequestMethod.POST可缺省
     * POST请求,请求体中携带添加数据的参数对象
     * 接收到请求体中的参数对象后,用实体类封装 @RequestBody
     *
     * @param sysEquipment 对象
     * @return 不返回数据
     */
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public Result saveEquipment(@RequestBody SysEquipment sysEquipment) {
        sysEquipment.setCreateTime(LocalDateTime.now());                          // 插入创建时间
        boolean saved = equipmentService.save(sysEquipment);                      // 返回结果
        return Result.success((saved ? "设备创建成功" : "创建失败"));
    }

    /**
     * 使用BaseMapper内建的删除方法,删除单个ID的设备,此方法无法更新updateTime
     * 注解 @RequsetMapping注解派生出@GetMapping、@PostMapping、@PutMapping和@DeleteMapping4个注解
     * 对应get/post/put/delete
     * 或者@RequestMapping+method参数
     * 注解 @PathVariable接收请求路径中的数据,用数据接收
     *
     * @param id 本表的id
     * @return 返回操作结果
     */
    @RequestMapping(value = "/deleteById/{id}", method = RequestMethod.DELETE)
    public Result equipmentDeleteById(@PathVariable("id") Long id) {
        boolean removed = equipmentService.removeById(id);
        return Result.success(removed ? "逻辑删除成功" : "删除失败");
    }

    /*
     * 未启用
     * 批量删除,无法更新updateTime
     * 接收POST请求,@RequestBody接收请求体,封装成list
     * 调用IService中的removeBatchByIds方法
     * POST请求,Body,json
     * */
    @RequestMapping(value = "/deleteBatchByIds", method = RequestMethod.POST)
    public Result equipmentDeleteBatchByIds(@RequestBody List<Long> deleteList) {
        boolean removed = equipmentService.removeBatchByIds(deleteList);
        return Result.success(removed ? "第 " + deleteList.toString() + " 条数据逻辑删除成功" : "删除失败");
    }

    /**
     * 使用BaseMapper内建的修改方法修改一组数据
     * 必须含有主键id,只修改equipmentName或information
     * 接收到请求体中的参数对象后,用实体类封装 @RequestBody
     *
     * @param sysEquipment POST对象
     * @return 返回操作结果
     */
    @RequestMapping(value = "/updateById", method = RequestMethod.POST)
    public Result updateEquipmentById(@RequestBody SysEquipment sysEquipment) {
        sysEquipment.setUpdateTime(LocalDateTime.now());
        boolean updateById = equipmentService.updateById(sysEquipment);
        return Result.success((updateById ? "修改成功" : "修改失败"));
    }

    /*
     * 不带条件的分页查询
     * 使用分页插件完成分页功能 mybatisplus.extension.plugins.pagination.Page;
     * POST请求体中携带分页对象{"current":页码,"size":每页几条数据},用map接收
     * */
    @RequestMapping(value = "/pages", method = RequestMethod.GET)
    public Result equipmentPages(Long current, Long size) {
        // 1.创建分页对象,并传入分页参数
        Page<SysEquipment> page = new Page<>(current, size);
        // 2.调用分页方法,返回分页对象
        Page<SysEquipment> equipment = equipmentService.page(page);
        return Result.success(equipment);
    }

    /*
     * 带组装条件的符合查询条件的分页查询
     * 分页参数用GET请求的Params传参,查询条件用请求体对象传参
     * 使用LambdaQueryWrapper用Lambda表达式直接访问实体类中的字段
     * 使用if(StringUtils.isNotBlank<T>) 判断组装条件,不为空时组装
     * 使用带condition参数的方法组装条件
     * eq完全相等,like字符串匹配
     * */
    @RequestMapping(value = "/queryWrapperPages", method = RequestMethod.POST)
    public Result equipmentQuery(Long current, Long size, @RequestBody SysEquipment sysEquipment) {
        IPage<SysEquipment> iPage = new Page<>(current, size);
        LambdaQueryWrapper<SysEquipment> queryWrapper = new LambdaQueryWrapper<>();
        // 带condition + StringUtils组装条件存在判断的构造方法
        queryWrapper.eq(StringUtils.isNotBlank(sysEquipment.getRoomId().toString()),
                SysEquipment::getRoomId, sysEquipment.getRoomId());
        queryWrapper.eq(StringUtils.isNotBlank(sysEquipment.getEquipmentName()),
                SysEquipment::getEquipmentName, sysEquipment.getEquipmentName());
        queryWrapper.eq(StringUtils.isNotBlank(sysEquipment.getEquipmentType()),
                SysEquipment::getEquipmentType, sysEquipment.getEquipmentType());
        queryWrapper.eq(StringUtils.isNotBlank(sysEquipment.getInformation()),
                SysEquipment::getInformation, sysEquipment.getInformation());
        queryWrapper.eq(StringUtils.isNotBlank(sysEquipment.getMac()),
                SysEquipment::getMac, sysEquipment.getMac());
        IPage<SysEquipment> page = equipmentService.page(iPage, queryWrapper);
        return Result.success(page);
    }

    /**
     * 设备查询,根据id查询设备,前端修改数据前的展示
     *
     * @param id sys_equipment 表的id
     * @return 统一的Result
     */
    @RequestMapping(value = "/listById/{id}", method = RequestMethod.GET)
    public Result listEquipmentById(@PathVariable("id") Long id) {
        SysEquipment byId = equipmentService.getById(id);
        return Result.success(byId);
    }

    /*
     * 未启用
     * 设备查询,根据roomId,查询设备,前端根据roomIds遍历用
     */
    @RequestMapping(value = "/listEquipmentByRoomId", method = RequestMethod.GET)
    public Result listEquipmentByRoomId(Long roomId) {
        LambdaQueryWrapper<SysEquipment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(SysEquipment::getRoomId, roomId);
        List<SysEquipment> list = equipmentService.list(lambdaQueryWrapper);
        return Result.success(list);
    }

    /*
     * 未启用
     * 设备查询,根据roomIds数组查询
     */
    @RequestMapping(value = "/listEquipmentByRoomIds", method = RequestMethod.POST)
    public Result listEquipmentByRoomId(@RequestBody List<Long> roomIds) {
        LambdaQueryWrapper<SysEquipment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(SysEquipment::getRoomId, roomIds);
        List<SysEquipment> listByIds = equipmentService.list(lambdaQueryWrapper);
        return Result.success(listByIds);
    }

    /**
     * 设备查询,管理员接口,只查询用户->户主->屋主->设备
     * 1. user_id 查询 sys_family 表,返回 List<family_ids>
     * 2. family_ids 查询 sys_room 表,返回 List<room_ids>
     * 3. room_ids 查询sys_equipment 表,返回 List<equipment>
     * 返回非嵌套的数据
     *
     * @param sysUserId 用户id
     * @return 统一的Result
     */
    @RequestMapping(value = "/listByUserId", method = RequestMethod.GET)
    public Result listEquipmentByUserId(Long sysUserId) {
        // 1. 第一次查询,user_id 查询 sys_family 表,返回 List<family_ids>
        LambdaQueryWrapper<SysFamily> sysFamilyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysFamilyLambdaQueryWrapper.select(SysFamily::getId)
                .eq(SysFamily::getSysUserId, sysUserId);
        List<SysFamily> familyList = familyService.list(sysFamilyLambdaQueryWrapper);
        // 2. 从返回的对象中获取id,stream的map操作
        List<Long> family_ids = familyList.stream().map(SysFamily::getId).toList();
        // 3. 第二次查询,family_ids 查询 sys_room 表,返回room_ids
        LambdaQueryWrapper<SysRoom> roomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomLambdaQueryWrapper.select(SysRoom::getId)
                .in(SysRoom::getFamilyId, family_ids);
        List<SysRoom> roomList = roomService.list(roomLambdaQueryWrapper);
        // 4. 从返回的对象中获取id,stream的map操作
        List<Long> room_ids = roomList.stream().map(SysRoom::getId).toList();
        // 5. 第三次查询,room_ids 查询 sys_equipment 表,返回 List<equipment>
        LambdaQueryWrapper<SysEquipment> equipmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        equipmentLambdaQueryWrapper.in(SysEquipment::getRoomId, room_ids);
        List<SysEquipment> list = equipmentService.list(equipmentLambdaQueryWrapper);
        return Result.success(list);
    }

    /**
     * 设备查询,管理查询接口
     * 1. 用 user_id 查询 sys_family 表,返回 List<family_ids>
     * 2. 用 familyIds 查询 sys_room 表,返回 List<SysRoom>
     * 3. 用 roomIds 查询 sys_equipment 表,返回 List<equipment>
     * 4. 3层对象数组嵌套 family->room->equipment
     *
     * @param sysUserId 用户id
     * @return 统一的Result
     */
    @RequestMapping(value = "/listFamilyRoomEquipmentByOwnerId", method = RequestMethod.GET)
    public Result listFamilyRoomEquipmentByOwnerId(Long sysUserId) {
        List<FamilyRoomEquipmentVO> familyRoomEquipmentVOS = equipmentService
                .selectFamilyRoomEquipmentByOwner(sysUserId);
        return Result.success(familyRoomEquipmentVOS);
    }

    /**
     * 设备查询,用户查询接口
     * 1. user_id 查询 sys_user_family 中间表,返回 List<family_ids>
     * 2. List<family_ids> 查询 sys_family 表,用于 PO->VO
     * 3. family_ids 查询 sys_room 表,返回 List<SysRoom>
     * 4. room_ids 查询sys_equipment 表,返回 List<equipment>
     * 5. 3层对象数组嵌套 family->room->equipment
     *
     * @param sysUserId 用户id
     * @return 统一的Result
     */
    @RequestMapping(value = "/listFamilyRoomEquipmentByUserId", method = RequestMethod.GET)
    public Result listFamilyRoomEquipmentByUserId(Long sysUserId) {
        List<FamilyRoomEquipmentVO> familyRoomEquipmentVOS = equipmentService
                .selectFamilyRoomEquipmentByUser(sysUserId);
        return Result.success(familyRoomEquipmentVOS);
    }

}
